import { createApp, toRaw,createVNode,render } from "vue";
import App from "./App.vue";
import router from "./router";
import Card from "./components/cardVue.vue";
//  注册全局组件
const app = createApp(App);
app.use(router).component("Card", Card);


//  设置loadding 遮罩层
//  插件使用=== 将组件封装为插件
import Loading from "./components/loading/loading";
app.use(Loading);

//  设置loadingBar
import loadingBar from './components/loading/loadingBar.vue'
const Vnode = createVNode(loadingBar)
render(Vnode, document.body)
console.log(Vnode);
 
router.beforeEach((to, from, next) => {
  document.title = to.meta.title // 这里报错需要在router.ts 中定义declare
    Vnode.component?.exposed?.startLoading()
    next()
})
router.afterEach((to, from) => {
    Vnode.component?.exposed?.endLoading()
})


import mitt from "mitt";
// const Mitt = mitt()
// declare modele "vue"{
//     export interface componentCustomProperties{
//         $Bus :typeof Mitt
//     }
// }
// app.config.globalPorperties.$Bus = Mitt   // 这样的方式定义全局变量挂载在vue原型上面，不同与vue2

// vue3 移除了过滤器 可以使用下面的方式使用
type Filter = {
  format: <T extends any>(str: T) => T;
};
// 声明要扩充@vue/runtime-core包的声明.
// 这里扩充"ComponentCustomProperties"接口, 因为他是vue3中实例的属性的类型.
declare module "@vue/runtime-core" {
  export interface ComponentCustomProperties {
    $filters: Filter;
    $env: string;
  }
}
app.config.globalProperties.$filters = {
  format<T>(str: T): string {
    return `真·${str}`;
  },
};
app.config.globalProperties.$env = "dev";



type Lod = {
  show: () => void;
  hide: () => void;
};
//编写ts loading 声明文件放置报错 和 智能提示
declare module "@vue/runtime-core" {
  export interface ComponentCustomProperties {
    $loading: Lod;
  }
}

//  使用pinia，如需要 ：加持久化操作
import { createPinia, PiniaPluginContext } from "pinia";
const store = createPinia();
const setStorageItem = (key: string, value: any) => {
  localStorage.setItem(key, JSON.stringify(value));
};
const getStorageItem = (key: string) => {
  return localStorage.getItem(key)
    ? JSON.parse(localStorage.getItem(key) as string)
    : {};
};
const __piniaKey: string = "pinia";
const piniaPlugin = (option: { key?: string }) => {
  return (context: PiniaPluginContext) => {
    const { store } = context;
    const data = getStorageItem(`${option.key ?? __piniaKey}-${store.$id}`);
    store.$subscribe(() => {
      setStorageItem(
        `${option.key ?? __piniaKey}-${store.$id}`,
        toRaw(store.$state)
      );
    });
    return { ...data };
  };
};
store.use(
  piniaPlugin({
    key: "pinia",
  })
);
app.use(store);
app.mount("#app");
